// -----------------------------------------------------------------
//     Learning Team C
//       Members:
//       Jon Mann
//       Jared Pack
//       Joshua Clayton
//     CS 4280  9:30 am
//     Team Assignment #4
//     Instructor: Mr. Rague
//     Due: 03/04/10
//     Version: 1.0
// -----------------------------------------------------------------
// This program builds a 3D scene 
// that uses the keyboard and mouse for interaction.
// -----------------------------------------------------------------


// -----------------------------------------------------------------
//   Change Control Section
// -----------------------------------------------------------------
//       Team Member:  Jon Mann
//       Version: 1.0
//       Date:  02/24/2010
//       Built a rough first run for program, 
//			borrowing heavily from the code in the book
//		 Included a table and a starter robot head (the teapot)
//		 Set up keyboard functions for model switching (wire frame to solid)
//			and visible/invisible switch
//		 Set up mouse function to rotate robot "head"
//
//       Team Member:  Jon Mann
//       Version: 1.1
//       Date:  02/26/2010
//       Added myIdle() to handle glutPostRedisplay()
//
//       Team Member:  Jon Mann
//       Version: 1.2
//       Date:  02/27/2010
//       Added a robot body
//		 Updated wireframe/solid code
//		 Updated visible/invisible code
//		 Replaced teapot head with new head built from spheres and cones
//
//       Team Member:  Jon Mann
//       Version: 1.2
//       Date:  03/01/2010
//       Added code to move point light with mouse
//		 Moved some rotational code out of mouseMove() function for modularity
//
//       Team Member:  Jon Mann
//       Version: 1.3
//       Date:  03/02/2010
//       Changed from orthographic view to perspective view
//		 Cleaned up some viewing problems
//		 Added rotation code to move the camera with the keyboard
//		 Added calcZ() function to keep the camera a specific 
//			distance from the center of scene (orbit)
//
//       Team Member:  Jared Pack
//       Version: 1.4
//       Date:  03/04/2010
//       Added the ability to select objects based on mouse clicks.  This selection is
//		 done to toggle the clicked object between solid and wireframe rendering.
//
// -----------------------------------------------------------------

#ifdef WIN32
#include <windows.h>
#endif

#include <GL/gl.h>
#include <GL/glu.h>
#include <GL/glut.h>
#include "reshape.h"

extern void robotHead(void);
extern void display(void);

// these hold our mouse coordinates
int mousePosX;
int mousePosY;

// these adjust the camera position
int camX;
int camY;
double dist;
double zDist;

// these help toggle object settings in the scene
bool solidTable;
bool solidRobot;
bool tableVisible;
bool robotVisible;

// this is the mouse event handler
// the x and y parameters are the mouse coordinates when the button was pressed
void mouse(int button, int state, int x, int y)
{

	GLint viewport[4];
	GLubyte p[3];

	//check for a left mouse click
	if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN)
	{
		glGetIntegerv(GL_VIEWPORT,viewport);

		//get the color value out of the mouse click
		glReadPixels(x,viewport[3]-y,1,1,
			GL_RGB,GL_UNSIGNED_BYTE,(void *)p);

		if(!solidTable && (x < (viewport[2]/2)))
			solidTable = true;
		if(!solidRobot && (x > (viewport[2]/2)))
			solidRobot = true;
		if(p[0] != 25 && p[1] != 25 && p[2] != 25){
			if(x > (viewport[2]/2))
				solidRobot = false;
			else
				solidTable = false;
		}		
	}
}
// this is the keyboard event handler
// the x and y parameters are the mouse coordinates when the key was struck
void keyboard(unsigned char key, int x, int y)
{
	switch(key)
	{
	case 't':
		tableVisible = !tableVisible;
		break;
	case 'r':
		robotVisible = !robotVisible;
		break;
	case 'w':
		camY += 10;
		break;
	case 's':
		camY -= 10;
		break;
	case 'a':
		camX -= 10;
		break;
	case 'd':
		camX += 10;
		break;
	default:
		break;
	}
}

void mouseMove(int x, int y)
{
//	cout << x;
	mousePosX = (float)x / glutGet(GLUT_WINDOW_WIDTH) * world_win_width;
	mousePosY = (1.0 - (float)y / glutGet(GLUT_WINDOW_HEIGHT)) * world_win_height;
	robotHead();
}

void init(void)
{
	mousePosX = 0;
	mousePosY = 0;
	tableVisible = true;
	robotVisible = true;
	solidTable = true;
	solidRobot = true;
	dist = 700;

        world_win_x = -320;
        world_win_y = -240.0;
        world_win_z = 500.0;
        world_win_width = 640.0;
        world_win_height = 480.0;
        world_win_depth = 1000.0;
}

void myIdle()
{
	glutPostRedisplay();
}

// main
int main(int argc, char **argv)
{
	glutInit(&argc, argv);
	glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
	glutInitWindowSize(640, 480);
	glutInitWindowPosition(100, 100);
	glutCreateWindow("shaded example - 3D scene");
	glEnable(GL_LIGHTING); // enable the light source
	glEnable(GL_LIGHT0);
	glShadeModel(GL_SMOOTH);
	glEnable(GL_DEPTH_TEST);  // for removal of hidden surfaces
	glEnable(GL_NORMALIZE);  // normalize vectors for proper shading
	glClearColor(0.1f, 0.1f, 0.1f, 0.0f);  // light gray background
	glViewport(0, 0, world_win_width, world_win_height);

	init();

	glutIdleFunc(myIdle);
	glutDisplayFunc(display);
	glutKeyboardFunc(keyboard);
	glutMouseFunc(mouse);
	glutPassiveMotionFunc(mouseMove); 
        glutReshapeFunc(keepWholeWindow);

	glutMainLoop();
}
